import java.util.ArrayList;


public class Production {

	private ArrayList<String> lhs;//le stringhe che formano la produzione insieme a key es: S -> ab|c, S=key e ab=lhs[0] e c=lhs[1]
	private String key;
	
	public Production(){
		
		this.lhs= new ArrayList<String>();
		key= "";
	}
	
	public Production(String prod, String delimiter, String k){
		
		if(delimiter.equals(null)) delimiter= ";";
		this.setLHS(prod, delimiter);
		this.setKey(k);
	}
	
	public void setKey(String k){
		
		this.key= k;
	}
	
	public void setLHS(String prod, String delimiter){
		
		this.lhs= Utility.ArrayToList(Utility.StringSplitByDelimiter(prod, delimiter));
	}
	
	public void addProduction(String prod){

		if(!this.lhs.contains(prod)) this.lhs.add(prod);
		else if(prod.equals("|")){
			
			if(!this.lhs.get(this.lhs.size()-1).equals("|")) this.lhs.add(prod);
		}
	}
	
	public ArrayList<String> getLHS(){
		
		return this.lhs;
	}
	
	public ArrayList<String> getLHScompact(){
		
		ArrayList<String> tmp= new ArrayList<String>();
		String str="";
		
		int size= 0;
		for(String a : this.lhs){
			
			size+= a.length();
		}
		
		for(String a : this.lhs){
			
			str+= a;
			if(a.equals("|")){
				
				String s= str.substring(0, str.indexOf("|"));
				tmp.add(s);
				size-= s.length()+1;
				str= "";
			}
			else if(str.indexOf(a)==size-1){

				//String s= str.substring(0);
				tmp.add(str);
				str="";
			}
		}
		
		return tmp;
	}
	
	public void replaceLHS(String B, ArrayList<String> lhs){

		//ArrayList<String> tmpLHS= this.normalToCompact(lhs);
		this.normalToCompact(lhs);
		ArrayList<String> tmp= this.normalToCompact(this.lhs);
		//ArrayList<String> LHS= new ArrayList<String>();
		this.lhs.clear();
		for(String s : tmp){
			
			//System.out.println("s= "+s);
			if(s.equals(B)){
				
				for(String b : lhs){

					//System.out.println("b= "+b);
					this.addProduction(b);
				}
			}
			else {
				this.addProduction(s);
			}
		}
		
		//this.lhs.clear();
		//this.compactToNormal(this.lhs);
		//this.lhs= this.compactToNormal(this.lhs);
	}
	
	public ArrayList<String> compactToNormal(ArrayList<String> lhs){
		
		ArrayList<String> tmp = new ArrayList<String>();
		for(String s : lhs){
			//System.out.println("s= "+s);

			for(char c : s.toCharArray()){

				//System.out.println("c= "+c);
				tmp.add(Character.toString(c));
			}
		}
		
		/*for(String g : tmp){
			
			System.out.println("g="+g);
		}*/
		
		return tmp;
	}
	

	public ArrayList<String> normalToCompact(ArrayList<String> lhs){
		
		ArrayList<String> tmp = new ArrayList<String>();
		String str= "";
		
		int size= 0;
		for(String a : lhs){
			
			size+= a.length();
		}
		
		for(String s : lhs){
			
			//System.out.println("size= "+size);
			str+= s;
			//System.out.println("str= "+str);
			if(s.equals("|")) {
				
				String sub= str.substring(0, str.indexOf(s));
				tmp.add(sub);
				tmp.add("|");
				size-= sub.length()+1;
				str= "";
			}
			else{ 
				
				if(str.length()==size){
				
				tmp.add(str);
				//tmp.add("|");
				str= "";
				}
			}
		}
		
		/*for(String g : tmp){
			
			System.out.println(g);
		}*/
		
		return tmp;
	}
	
	public String getKey(){
		
		return this.key;
	}
	
	public int removeProduction(int indexOf){

		if(indexOf==this.lhs.size()-1 && this.lhs.get(indexOf-1).equals("|")){

			this.lhs.remove(indexOf);
			this.lhs.remove(indexOf-1);
		}
		else if(this.lhs.get(indexOf-1).equals("|") && this.lhs.get(indexOf+1).equals("|")){

			this.lhs.remove(indexOf);
			this.lhs.remove(indexOf-1);
		}
		
		return 0;
	}
	
	//funziona solo se gli elementi di lhs sono unici, altrimenti ne rimuove solo il primo
	public int removeProduction(String s){
		
		int indexOf= this.lhs.indexOf(s);
		if(indexOf==this.lhs.size()-1 && this.lhs.get(indexOf-1).equals("|")){

			this.lhs.remove(indexOf);
			this.lhs.remove(indexOf-1);
		}
		else if(this.lhs.get(indexOf-1).equals("|") && this.lhs.get(indexOf+1).equals("|")){

			this.lhs.remove(indexOf);
			this.lhs.remove(indexOf-1);
		}
		
		return 0;
	}
	
	public boolean noMoreProductions(){
		
		if(this.lhs.size() < 1) return true;
		
		return false;
	}
	
	public static void main(String[] args){
		
		Grammar g= new Grammar("S->AS|A;A->a|B;B->b|S|A;", "S");
		ArrayList<Production> p= g.getP().getLHS();
		for(Production pp : p){
			
			pp.normalToCompact(pp.lhs);
			pp.compactToNormal(pp.lhs);
			System.out.println("=============");
		}
	}
}
